package cn.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class FTPHandler {
	Socket socket = null;
	Socket transSocket = null;
	BufferedReader is = null;
	PrintWriter os = null;
	DataTransmittor dt = null;

	public FTPHandler(Socket s) {
		if (s != null) {
			socket = s;
			try {
				is = new BufferedReader(new InputStreamReader(
						socket.getInputStream()));
				os = new PrintWriter(socket.getOutputStream());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.out.println(e);
			}
		}
	}

	public synchronized String readLine() {
		String line = null;
		try {
			line = is.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		System.out.println("Recv: " + line);
		return line;
	}

	public synchronized void writeLine(String line) {
		if (line != null && line.length() > 0) {
			if (!line.endsWith(MyUtil.CRLF)) {
				line = line.trim() + MyUtil.CRLF;
			}
			os.write(line);
			os.flush();
//			System.out.println("Send: " + line);
		}
	}

	public boolean isReady() {
		return socket.isConnected();
	}

	public void close() {
		try {
			if (os != null)
				os.close();
			if (is != null)
				is.close();
			if (socket != null)
				socket.close();
		} catch (IOException e) {
			System.out.println("Error when closing: " + e);

		}
	}
	
	public void setPath(String path, boolean isSend) {
		if (dt != null) {
//			System.out.println("Setting path to " + path);
			dt.setPath(path, isSend);
//			System.out.println("isSend = " + isSend);
		}
	}

	public void buildTransSocket(int port) {
		dt = new DataTransmittor(port, false);
//		Thread thread = new Thread(dt);
//		thread.start();
	}

	public void buildTransServer(int port) {
		dt = new DataTransmittor(port, true);
//		Thread thread = new Thread(dt);
//		thread.start();
	}
}

class DataTransmittor implements Runnable{

	private Socket transSocket = null;
	private int port = 0;
	private boolean isSend = false;
	private boolean isPasv = false;
	private String filepath = null;
	
	public DataTransmittor(int port, boolean isPasv) {
		this.isPasv = isPasv;
		this.port = port;
	}

	public void setPath(String path, boolean isSend) {
		this.filepath = path;
		this.isSend = isSend;
		
		Thread thread = new Thread(this);
		thread.start();
	}
	
	public void buildTransServer(int port) {
		try {
			ServerSocket ss = new ServerSocket(port);
//			System.out.println("Waiting for client...");
			transSocket = ss.accept();
//			System.out.println("The client has connected");
			if (isSend) {
//				System.out.println("Begin to send file");
				this.sendFile(filepath);
			} else {
//				System.out.println("Begin to receive file");
				this.recvFile(filepath);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void buildTransSocket(int port) {
//		System.out.println("new port = " + port);
		try {
			transSocket = new Socket(MyUtil.defaultIp, port);
			if (isSend) {
//				System.out.println("Begin to send file");
				this.sendFile(filepath);
			} else {
//				System.out.println("Begin to receive file");
				this.recvFile(filepath);
			}
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void sendFile(String filepath) {
		File file = new File(filepath);
		if (!file.exists() && !file.isFile()) {
			System.out.println("Cannot find file");
			return;
		}
		if (transSocket == null) {
			return;
		}

//		System.out.println("Sending file");
		DataInputStream dis;
		try {
			dis = new DataInputStream(new BufferedInputStream(
					transSocket.getInputStream()));
			DataInputStream fis = new DataInputStream(new BufferedInputStream(
					new FileInputStream(filepath)));
			DataOutputStream ps = new DataOutputStream(
					transSocket.getOutputStream());
			ps.writeUTF(file.getName());
			ps.flush();
			ps.writeLong((long) file.length());
			ps.flush();
			int bufferSize = 8192;
			byte[] buf = new byte[bufferSize];

			while (true) {
				int read = 0;
				if (fis != null) {
					read = fis.read(buf);
				}

				if (read == -1) {
					break;
				}
				ps.write(buf, 0, read);
			}
			ps.flush();
			fis.close();
			transSocket.close();
			if (!filepath.endsWith("dirInfo")) {
				System.out.println("Successfully sent file " + filepath);
			} else {
				File f = new File(filepath);
				f.delete();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void recvFile(String filepath) {
		if (transSocket == null) {
			return;
		}
		
		try {
			DataInputStream inputStream = new DataInputStream(
					new BufferedInputStream(transSocket.getInputStream()));
			int bufferSize = 8192;
			byte[] buf = new byte[bufferSize];
			int passedlen = 0;
			long len = 0;

			filepath += inputStream.readUTF();
			DataOutputStream fileOut = new DataOutputStream(
					new BufferedOutputStream(new BufferedOutputStream(
							new FileOutputStream(filepath))));
			len = inputStream.readLong();

			while (true) {
				int read = 0;
				if (inputStream != null) {
					read = inputStream.read(buf);
				}
				passedlen += read;
				if (read == -1) {
					break;
				}
				fileOut.write(buf, 0, read);
			}
			
			fileOut.close();
			if (filepath.endsWith("dirInfo")) {
				String temp = null;
				MyFileReader mfr = new MyFileReader(filepath);
				while ((temp = mfr.getNextLine()) != null) {
					System.out.println(temp);
				}
				mfr.close();
				File f = new File(filepath);
				f.delete();
			} else {
				System.out.println("Successfully receive file " + filepath);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		if (isPasv) {
			buildTransServer(port);
		} else {
			buildTransSocket(port);
		}
		
	}
	
	
}
